home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 4 / Amiga Tools 4.iso / grafix / tools / amipeg_0.4 / video.c < prev    next >
C/C++ Source or Header  |  1994-04-22  |  56KB  |  2,099 lines

  1. /*
  2.  *  This file contains C code that implements the video decoder model.
  3.  */
  4.  
  5. #include "video.h"
  6. #include "proto.h"
  7. #include "decoders.h"
  8. #include "util.h"
  9.  
  10. #include <time.h>
  11.  
  12. #define MYRECON
  13.  
  14. /* Declarations of functions. */
  15. //static void init_stat_struct(Statval *);
  16. //static void PrintOneStat(void);
  17. //static void CollectStats(void);
  18. //static unsigned int bitCountRead(void);
  19. //static void StartTime(void);
  20. //static void EndTime(void);
  21. static int ParseSeqHead(VidStream *);
  22. static int ParseGOP(VidStream *);
  23. static int ParsePicture(VidStream *, TimeStamp);
  24. static int ParseSlice(VidStream *);
  25. static int ParseMacroBlock(VidStream *);
  26. static void DoPictureDisplay(VidStream *);
  27.  
  28. #ifndef MYRECON
  29. static void ReconIMBlock(VidStream *, int);
  30. static void ReconPMBlock(VidStream *, int, int, int, int);
  31. static void ReconBMBlock(VidStream *, int, int, int, int);
  32. static void ReconBiMBlock(VidStream *, int, int, int, int, int, int);
  33. #endif
  34.  
  35. static void ProcessSkippedPFrameMBlocks(VidStream *);
  36. static void ProcessSkippedBFrameMBlocks(VidStream *);
  37. static void ReconSkippedBlock16(unsigned char *, unsigned char *, int, int, int, int, int, int, int);
  38. static void ReconSkippedBlock8(unsigned char *, unsigned char *, int, int, int, int, int, int, int);
  39.  
  40. extern int ditherType;
  41.  
  42. /* Macro for returning 1 if num is positive, -1 if negative, 0 if 0. */
  43. //#define Sign(num) ((num > 0) ? 1 : ((num == 0) ? 0 : -1))
  44.  
  45. /* Declare global pointer to vid stream used for current decoding. */
  46.  
  47. VidStream *curVidStream = NULL;
  48.  
  49. /* Array mapping zigzag to array pointer offset. */
  50. int zigzag_direct[64] = {
  51.   0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12,
  52.   19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35,
  53.   42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
  54.   58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63};
  55.  
  56. /* Initialize P and B skip flags. */
  57.  
  58. static int No_P_Flag = 0;
  59. static int No_B_Flag = 0;
  60.  
  61. /* Max lum, chrom indices for illegal block checking. */
  62.  
  63. static int lmaxx, lmaxy, cmaxx, cmaxy;
  64.  
  65.  
  66. /*
  67.   The following accounts for time and size  spent in various parsing acitivites
  68.   if ANALYSIS has been defined.
  69. */
  70. #ifdef ANALYSIS
  71. #include "analysis.h"
  72. #endif
  73.  
  74. double realTimeStart;
  75. int totNumFrames = 0;
  76.  
  77. double ReadSysClock(void)
  78. {
  79.     unsigned int clock[2];
  80.  
  81.     (void) timer(clock);
  82.     return clock[0] + clock[1] / 1000000.0;
  83. }
  84.  
  85. void PrintTimeInfo(void)
  86. {
  87.     if (!quietFlag) {
  88.         double spent = ReadSysClock() - realTimeStart;
  89.  
  90.         printf("\nReal Time Spent (After Initializations): %f secs.\n", spent);
  91.         printf("Avg. Frames/Sec: %f\n", ((double) totNumFrames) / spent);
  92.  
  93.         printf("Frame size: %i*%i pixels\n", curVidStream->h_size, curVidStream->v_size);
  94.     }
  95. }
  96.  
  97.  
  98.  
  99. /*
  100.  *--------------------------------------------------------------
  101.  *
  102.  * NewVidStream --
  103.  *
  104.  *    Allocates and initializes a VidStream structure. Takes
  105.  *      as parameter requested size for buffer length.
  106.  *
  107.  * Results:
  108.  *    A pointer to the new VidStream structure.
  109.  *
  110.  * Side effects:
  111.  *      None.
  112.  *
  113.  *--------------------------------------------------------------
  114.  */
  115.  
  116. VidStream * NewVidStream(int bufLength)
  117. {
  118.   int i,j;
  119.   short *intra_quant_matrix, *intra_quant_matrix0, *intra_quant_matrix1;
  120.   VidStream *new;
  121.   static unsigned char default_intra_matrix[64] = {
  122.     8, 16, 19, 22, 26, 27, 29, 34,
  123.     16, 16, 22, 24, 27, 29, 34, 37,
  124.     19, 22, 26, 27, 29, 34, 34, 38,
  125.     22, 22, 26, 27, 29, 34, 37, 40,
  126.     22, 26, 27, 29, 32, 35, 40, 48,
  127.     26, 27, 29, 32, 35, 40, 48, 58,
  128.     26, 27, 29, 34, 38, 46, 56, 69,
  129.     27, 29, 35, 38, 46, 56, 69, 83};
  130.  
  131.   /* Check for legal buffer length. */
  132.  
  133.   if (bufLength < 4) return NULL;
  134.  
  135.   /* Make buffer length multiple of 4. */
  136.  
  137.   bufLength = (bufLength + 3) >> 2;
  138.  
  139.   /* Allocate memory for new structure. */
  140.  
  141.   new = (VidStream *) malloc(sizeof(VidStream));
  142.  
  143.   /* Initialize pointers to extension and user data. */
  144.  
  145.   new->group.ext_data = new->group.user_data =
  146.     new->picture.extra_info = new->picture.user_data =
  147.     new->picture.ext_data = new->slice.extra_info =
  148.     new->ext_data = new->user_data = NULL;
  149.  
  150.   /* Create default intra matrix and qscale multiplication tables. */
  151.  
  152.   new->intra_quant_matrix_ptr[0] = (short*) malloc(32 * 8*8 * sizeof(short));
  153.   clear64words(intra_quant_matrix = new->intra_quant_matrix_ptr[0]);
  154.   for(j=1; j<32; j++) new->intra_quant_matrix_ptr[j] = (intra_quant_matrix+=64);
  155.  
  156.   intra_quant_matrix0 = intra_quant_matrix = new->intra_quant_matrix_ptr[1];
  157.  
  158.   for(i=0; i<64; i++)
  159.     *intra_quant_matrix++ = default_intra_matrix[zigzag_direct[i]];
  160.  
  161.   for(j=2; j<32; j++)
  162.   {
  163.     intra_quant_matrix1 = new->intra_quant_matrix_ptr[1];
  164.     for(i=0; i<64; i++) *intra_quant_matrix++ = (*intra_quant_matrix0++) + (*intra_quant_matrix1++);
  165.   }
  166.  
  167.   /* Initialize non intra quantization matrix. */
  168.  
  169.   new->non_intra_default = TRUE;
  170.   new->non_intra_quant_matrix_ptr[0] = NULL;
  171.  
  172.   /* Initialize pointers to image spaces. */
  173.  
  174.   new->current = new->past = new->future = NULL;
  175.   for (i = 0; i < RING_BUF_SIZE; i++) new->ring[i] = NULL;
  176.  
  177.   /* Create buffer. */
  178.  
  179.   new->buf_start = (unsigned int *) malloc(bufLength * 4);
  180.  
  181.   /*
  182.    * Set max_buf_length to one less than actual length to deal with messy
  183.    * data without proper seq. end codes.
  184.    */
  185.  
  186.   new->max_buf_length = bufLength - 1;
  187.  
  188.   /* Initialize bitstream i/o fields. */
  189.  
  190.   new->bit_offset = 0;
  191.   new->buf_length = 0;
  192.   new->buffer = new->buf_start;
  193.  
  194.   /* display stuff */
  195.  
  196.   new->display_is_initialized = FALSE;
  197.  
  198.   /* Return structure. */
  199.  
  200.   return new;
  201. }
  202.  
  203.  
  204.  
  205. /*
  206.  *--------------------------------------------------------------
  207.  *
  208.  * DestroyVidStream --
  209.  *
  210.  *    Deallocates a VidStream structure.
  211.  *
  212.  * Results:
  213.  *      None.
  214.  *
  215.  * Side effects:
  216.  *    None.
  217.  *
  218.  *--------------------------------------------------------------
  219.  */
  220. void DestroyVidStream(VidStream *astream)
  221. {
  222.   int i;
  223.  
  224.   if (astream->ext_data) free(astream->ext_data);
  225.  
  226.   if (astream->user_data) free(astream->user_data);
  227.  
  228.   if (astream->group.ext_data) free(astream->group.ext_data);
  229.  
  230.   if (astream->group.user_data) free(astream->group.user_data);
  231.  
  232.   if (astream->picture.extra_info) free(astream->picture.extra_info);
  233.  
  234.   if (astream->picture.ext_data) free(astream->picture.ext_data);
  235.  
  236.   if (astream->picture.user_data) free(astream->picture.user_data);
  237.  
  238.   if (astream->slice.extra_info) free(astream->slice.extra_info);
  239.  
  240.   if (astream->buf_start) free(astream->buf_start);
  241.  
  242.   for (i = 0; i < RING_BUF_SIZE; i++) {
  243.     if (astream->ring[i]) {
  244.       DestroyPictImage(astream->ring[i]);
  245.       astream->ring[i] = NULL;
  246.     }
  247.   }
  248.  
  249.   if (!astream->non_intra_default) free(astream->non_intra_quant_matrix_ptr[0]);
  250.  
  251.   if (astream->intra_quant_matrix_ptr[0]) free(astream->intra_quant_matrix_ptr[0]);
  252.  
  253.   free((char *) astream);
  254. }
  255.  
  256.  
  257.  
  258.  
  259. /*
  260.  *--------------------------------------------------------------
  261.  *
  262.  * NewPictImage --
  263.  *
  264.  *    Allocates and initializes a PictImage structure.
  265.  *      The width and height of the image space are passed in
  266.  *      as parameters.
  267.  *
  268.  * Results:
  269.  *    A pointer to the new PictImage structure.
  270.  *
  271.  * Side effects:
  272.  *    None.
  273.  *
  274.  *--------------------------------------------------------------
  275.  */
  276.  
  277. PictImage * NewPictImage(unsigned int width, unsigned int height)
  278. {
  279.   extern int lores, ham6;
  280.   PictImage *new;
  281.   int size = (short)width * (short)height;
  282.  
  283.   /* Allocate memory space for new structure. */
  284.  
  285.   new = (PictImage *) malloc(sizeof(PictImage));
  286.  
  287.   /* Allocate memory for image spaces. */
  288.   if (ditherType == FULL_COLOR_DITHER) {
  289.     new->display = (unsigned char *) malloc(ham6 ? size : (lores ? (size << 1) : (size << 2)));
  290.   } else {
  291.     new->display = (unsigned char *) malloc(size);
  292.   }
  293.  
  294.   new->luminance = (unsigned char *) malloc(size);
  295.   new->Cr = (unsigned char *) malloc(size >> 2);
  296.   new->Cb = (unsigned char *) malloc(size >> 2);
  297.  
  298.   /* Reset locked flag. */
  299.  
  300.   new->locked = 0;
  301.  
  302.   /* Return pointer to new structure. */
  303.  
  304.   return new;
  305. }
  306.  
  307.  
  308.  
  309. /*
  310.  *--------------------------------------------------------------
  311.  *
  312.  * DestroyPictImage --
  313.  *
  314.  *    Deallocates a PictImage structure.
  315.  *
  316.  * Results:
  317.  *      None.
  318.  *
  319.  * Side effects:
  320.  *    None.
  321.  *
  322.  *--------------------------------------------------------------
  323.  */
  324. void DestroyPictImage(PictImage *apictimage)
  325. {
  326.   if (apictimage->luminance) free(apictimage->luminance);
  327.   if (apictimage->Cr) free(apictimage->Cr);
  328.   if (apictimage->Cb) free(apictimage->Cb);
  329.   if (apictimage->display) free(apictimage->display);
  330.   free(apictimage);
  331. }
  332.  
  333. /*
  334.  *--------------------------------------------------------------
  335.  *
  336.  * mpegInitVidRsrc --
  337.  *
  338.  *      reset first to 1
  339.  *
  340.  * gonna check this thingy out !!!!
  341.  *
  342.  *--------------------------------------------------------------
  343.  */
  344. static int first = 1;
  345.  
  346. void mpegInitVidRsrc(void)
  347. {
  348.     first = 1;
  349. }
  350.  
  351.  
  352. /*
  353.  *--------------------------------------------------------------
  354.  *
  355.  * mpegVidRsrc --
  356.  *
  357.  *      Parses bit stream until MB_QUANTUM number of
  358.  *      macroblocks have been decoded or current slice or
  359.  *      picture ends, whichever comes first. If the start
  360.  *      of a frame is encountered, the frame is time stamped
  361.  *      with the value passed in time_stamp. If the value
  362.  *      passed in buffer is not null, the video stream buffer
  363.  *      is set to buffer and the length of the buffer is
  364.  *      expected in value passed in through length. The current
  365.  *      video stream is set to vid_stream. If vid_stream
  366.  *      is passed as NULL, a new VidStream structure is created
  367.  *      and initialized and used as the current video stream.
  368.  *
  369.  * Results:
  370.  *      A Boolean value is returned - 0 is end of picture or error
  371.  *
  372.  * Side effects:
  373.  *      Bit stream is irreversibly parsed. If a picture is completed,
  374.  *      a function is called to display the frame at the correct time.
  375.  *
  376.  *--------------------------------------------------------------
  377.  */
  378.  
  379. int mpegVidRsrc(TimeStamp time_stamp, VidStream *vid_stream)
  380. {
  381.   unsigned int data;
  382.   int i, status;
  383.  
  384.   /* If vid_stream is null, create new VidStream structure.  MR: ????? */
  385.  
  386.   if (vid_stream == NULL) return 0;
  387.  
  388.   /*
  389.    * Set global curVidStream to vid_stream. Necessary because bit i/o use
  390.    * curVidStream and are not passed vid_stream. Also set global bitstream
  391.    * parameters.
  392.    */
  393.  
  394.   curVidStream = vid_stream;
  395.   bitOffset = curVidStream->bit_offset;
  396.   bufLength = curVidStream->buf_length;
  397.   bitBuffer = curVidStream->buffer;
  398.  
  399.   /*
  400.    * If called for the first time, find start code, make sure it is a
  401.    * sequence start code.
  402.    */
  403.  
  404.   if (first) {
  405.     next_start_code();
  406.     if (show_bits32(data) != SEQ_START_CODE) {
  407.       fprintf(stderr, "This is not an MPEG stream.\n");
  408.       DestroyVidStream(curVidStream);
  409.       exit(1);
  410.     }
  411.     first = 0;
  412.   }
  413.  
  414.   /*
  415.    * Process according to start code (or parse macroblock if not a start code
  416.    * at all.
  417.    */
  418.  
  419.   switch (show_bits32(data)) {
  420.  
  421.   case SEQ_END_CODE:
  422.  
  423.     /* Display last frame. */
  424.  
  425.     if (vid_stream->future != NULL) {
  426.       vid_stream->current = vid_stream->future;
  427.       ExecuteDisplay(vid_stream);
  428.     }
  429.     
  430.     /* Sequence done. Do the right thing. return False. */
  431.  
  432.     if (!quietFlag) {
  433.       fprintf(stderr, "\nDone!\n");
  434.     }
  435.  
  436. #ifdef ANALYSIS
  437.     PrintAllStats();
  438. #endif
  439.     PrintTimeInfo();
  440.  
  441.     if (loopFlag) longjmp(env, 1);
  442.  
  443.     DestroyVidStream(curVidStream);
  444.     return 0;
  445.     break;
  446.  
  447.   case SEQ_START_CODE:
  448.  
  449.     /* Sequence start code. Parse sequence header. */
  450.  
  451.     if (ParseSeqHead(vid_stream) != PARSE_OK) goto error;
  452.  
  453.     /*
  454.      * Return after sequence start code so that application above can use
  455.      * info in header.
  456.      */
  457.  
  458.     goto done;
  459.  
  460.   case GOP_START_CODE:
  461.  
  462.     /* Group of Pictures start code. Parse gop header. */
  463.  
  464.     if (ParseGOP(vid_stream) != PARSE_OK) goto error;
  465.  
  466.  
  467.   case PICTURE_START_CODE:
  468.  
  469.     /* Picture start code. Parse picture header and first slice header. */
  470.  
  471.     status = ParsePicture(vid_stream, time_stamp);
  472.  
  473.     if (status == SKIP_PICTURE) {
  474.       next_start_code();
  475.       fprintf(stderr, "Skipping picture...");
  476.       while ((show_bits32(data)) != PICTURE_START_CODE) {
  477.     if (data == GOP_START_CODE || data == SEQ_END_CODE)
  478.       break;
  479.     flush_bits(24);
  480.     next_start_code();
  481.       }
  482.       fprintf(stderr, "Done.\n");
  483.       goto done;
  484.     } else if (status != PARSE_OK) goto error;
  485.  
  486.  
  487.     if (ParseSlice(vid_stream) != PARSE_OK) goto error;
  488.     break;
  489.  
  490.   case USER_START_CODE:    // there has been one stream with an error in a GOP header
  491.     flush_bits32;
  492.     if (vid_stream->group.user_data) {
  493.       free(vid_stream->group.user_data);
  494.       vid_stream->group.user_data = NULL;
  495.     }
  496.     vid_stream->group.user_data = get_ext_data();
  497.     break;
  498.   case EXT_START_CODE:
  499.     flush_bits32;
  500.     if (vid_stream->group.ext_data) {
  501.       free(vid_stream->group.ext_data);
  502.       vid_stream->group.ext_data = NULL;
  503.     }
  504.     vid_stream->group.ext_data = get_ext_data();
  505.     break;
  506.  
  507.   default:
  508.     /* Check for slice start code. */
  509.  
  510.     if ((data >= SLICE_MIN_START_CODE) && (data <= SLICE_MAX_START_CODE))
  511.       if (ParseSlice(vid_stream) != PARSE_OK)    /* Slice start code. Parse slice header. */
  512.     goto error;
  513.  
  514.     break;
  515.   }
  516.  
  517.   /* Parse next MB_QUANTUM macroblocks. */
  518.  
  519.   for (i = 0; i < MB_QUANTUM; i++) {
  520.  
  521.     /* Check to see if actually a startcode and not a macroblock. */
  522.  
  523.     if ((show_bitsn(23,data)) != 0x00000000) {
  524.  
  525.       /* Not start code. Parse Macroblock. */
  526.  
  527.       if (ParseMacroBlock(vid_stream) != PARSE_OK)
  528.     goto error;
  529.  
  530. #ifdef ANALYSIS
  531.       if (showmb_flag) {
  532.     DoDitherImage(vid_stream->current->luminance, vid_stream->current->Cr,
  533.               vid_stream->current->Cb, vid_stream->current->display,
  534.               vid_stream->mb_height * 16, vid_stream->mb_width * 16);
  535.     ExecuteDisplay(vid_stream);
  536.       }
  537. #endif
  538.  
  539.     } else {
  540.  
  541.       /* Not macroblock, actually start code. Get start code. */
  542.  
  543.       next_start_code();
  544.       show_bits32(data);
  545.  
  546.       /*
  547.        * If start code is outside range of slice start codes, frame is
  548.        * complete, display frame.
  549.        */
  550.  
  551.       if ((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) {
  552.  
  553. #ifdef ANALYSIS
  554.     EndTime();
  555.     stat_a[0].totsize += bitCountRead() - pictureSizeCount;
  556.     if (showEachFlag)
  557.       PrintOneStat();
  558.  
  559.     CollectStats();
  560. #endif
  561.  
  562.     DoPictureDisplay(vid_stream);
  563.       }
  564.       break;
  565.     }
  566.   }
  567.  
  568.   /* Return pointer to video stream structure. */
  569.  
  570.   goto done;
  571.  
  572. error:
  573.   fprintf(stderr, "Error!!!!\n");
  574.   next_start_code();
  575.   goto done;
  576.  
  577. done:
  578.  
  579.   /* Copy global bit i/o variables back into vid_stream. */
  580.  
  581.   vid_stream->buffer = bitBuffer;
  582.   vid_stream->buf_length = bufLength;
  583.   vid_stream->bit_offset = bitOffset;
  584.  
  585.   return 1;
  586. }
  587.  
  588.  
  589. /*
  590.  *--------------------------------------------------------------
  591.  *
  592.  * ParseSeqHead --
  593.  *
  594.  *      Assumes bit stream is at the begining of the sequence
  595.  *      header start code. Parses off the sequence header.
  596.  *
  597.  * Results:
  598.  *      Fills the vid_stream structure with values derived and
  599.  *      decoded from the sequence header. Allocates the pict image
  600.  *      structures based on the dimensions of the image space
  601.  *      found in the sequence header.
  602.  *
  603.  * Side effects:
  604.  *      Bit stream irreversibly parsed off.
  605.  *
  606.  *--------------------------------------------------------------
  607.  */
  608.  
  609. static int ParseSeqHead(VidStream *vid_stream)
  610. {
  611.   unsigned int data;
  612.   int i;
  613.  
  614.   /* Flush off sequence start code. */
  615.  
  616.   flush_bits32;
  617.  
  618.   /* Get horizontal size of image space. */
  619.  
  620.   get_bits12(vid_stream->h_size);
  621.  
  622.   /* Get vertical size of image space. */
  623.  
  624.   get_bits12(vid_stream->v_size);
  625.  
  626.   /* Calculate macroblock width and height of image space. */
  627.  
  628.   vid_stream->mb_width = (vid_stream->h_size + 15) >> 4;
  629.   vid_stream->mb_height = (vid_stream->v_size + 15) >> 4;
  630.  
  631.   /* Initialize lmaxx, lmaxy, cmaxx, cmaxy. */
  632.  
  633.   lmaxx = (vid_stream->mb_width<<4)-1;
  634.   lmaxy = (vid_stream->mb_height<<4)-1;
  635.   cmaxx = (vid_stream->mb_width<<3)-1;
  636.   cmaxy = (vid_stream->mb_height<<3)-1;
  637.  
  638.   /*
  639.    * Initialize ring buffer of pict images now that dimensions of image space
  640.    * are known.
  641.    */
  642.  
  643.   if (vid_stream->ring[0] == NULL) {
  644.     for (i = 0; i < RING_BUF_SIZE; i++)
  645.       vid_stream->ring[i] = NewPictImage(vid_stream->mb_width << 4, vid_stream->mb_height << 4);
  646.   }
  647.  
  648.   /* Parse of aspect ratio code. */
  649.  
  650.   get_bits4(vid_stream->aspect_ratio);
  651.  
  652.   /* Parse off picture rate code. */
  653.  
  654.   get_bits4(vid_stream->picture_rate);
  655.  
  656.   /* Parse off bit rate. */
  657.  
  658.   get_bits18(vid_stream->bit_rate);
  659.  
  660.   /* Flush marker bit. */
  661.  
  662.   flush_bits(1);
  663.  
  664.   /* Parse off vbv buffer size. */
  665.  
  666.   get_bits10(vid_stream->vbv_buffer_size);
  667.  
  668.   /* Parse off contrained parameter flag. */
  669.  
  670.   get_bits1(vid_stream->const_param_flag);
  671.  
  672.   /*
  673.    * If intra_quant_matrix_flag set, parse off intra quant matrix values.
  674.    */
  675.  
  676.   if (get_bits1(data))
  677.     new_matrix(vid_stream->intra_quant_matrix_ptr[1]);
  678.  
  679.   /*
  680.    * If non intra quant matrix flag set, parse off non intra quant matrix
  681.    * values.
  682.    */
  683.  
  684.   if (get_bits1(data))
  685.   {
  686.     if(vid_stream->non_intra_default)
  687.     {
  688.     unsigned short *intra_quant_matrix;
  689.  
  690.     vid_stream->non_intra_quant_matrix_ptr[0] = (short*) malloc(32 * 8*8 * sizeof(short));
  691.     clear64words(intra_quant_matrix = vid_stream->non_intra_quant_matrix_ptr[0]);
  692.     for(i=1; i<32; i++) vid_stream->non_intra_quant_matrix_ptr[i] = (intra_quant_matrix+=64);
  693.  
  694.     vid_stream->non_intra_default = FALSE;
  695.     }
  696.  
  697.     new_matrix(vid_stream->non_intra_quant_matrix_ptr[1]);
  698.   }
  699.  
  700.   /* Go to next start code. */
  701.  
  702.   next_start_code();
  703.  
  704.   /* If next start code is extension start code, parse off extension data. */
  705.  
  706.   if ((show_bits32(data)) == EXT_START_CODE) {
  707.     flush_bits32;
  708.     if (vid_stream->ext_data) {
  709.       free(vid_stream->ext_data);
  710.       vid_stream->ext_data = NULL;
  711.     }
  712.     vid_stream->ext_data = get_ext_data();
  713.     show_bits32(data);
  714.   }
  715.  
  716.   /* If next start code is user start code, parse off user data. */
  717.  
  718.   if (data == USER_START_CODE) {
  719.     flush_bits32;
  720.     if (vid_stream->user_data) {
  721.       free(vid_stream->user_data);
  722.       vid_stream->user_data = NULL;
  723.     }
  724.     vid_stream->user_data = get_ext_data();
  725.   }
  726.  
  727.   return PARSE_OK;
  728. }
  729.  
  730.  
  731.  
  732. /*
  733.  *--------------------------------------------------------------
  734.  *
  735.  * ParseGOP --
  736.  *
  737.  *      Parses of group of pictures header from bit stream
  738.  *      associated with vid_stream.
  739.  *
  740.  * Results:
  741.  *      Values in gop header placed into video stream structure.
  742.  *
  743.  * Side effects:
  744.  *      Bit stream irreversibly parsed.
  745.  *
  746.  *--------------------------------------------------------------
  747.  */
  748.  
  749. static int ParseGOP(VidStream *vid_stream)
  750. {
  751.   unsigned int data;
  752.  
  753.   /* Flush group of pictures start code. WWWWWWOOOOOOOSSSSSSHHHHH!!! */
  754.  
  755.   flush_bits32;
  756.  
  757.   /* Parse off drop frame flag. */
  758.  
  759.   get_bits1(vid_stream->group.drop_flag);
  760.  
  761.   /* Parse off hour component of time code. */
  762.  
  763.   get_bits5(vid_stream->group.tc_hours);
  764.  
  765.   /* Parse off minute component of time code. */
  766.  
  767.   get_bits6(vid_stream->group.tc_minutes);
  768.  
  769.   /* Flush marker bit. */
  770.  
  771.   flush_bits(1);
  772.  
  773.   /* Parse off second component of time code. */
  774.  
  775.   get_bits6(vid_stream->group.tc_seconds);
  776.  
  777.   /* Parse off picture count component of time code. */
  778.  
  779.   get_bits6(vid_stream->group.tc_pictures);
  780.  
  781.   /* Parse off closed gop and broken link flags. */
  782.  
  783.   get_bits1(vid_stream->group.closed_gop);
  784.   get_bits1(vid_stream->group.broken_link);
  785.  
  786.   /* Goto next start code. */
  787.   next_start_code();
  788.  
  789.   /* If next start code is extension data, parse off extension data. */
  790.  
  791.   if ((show_bits32(data)) == EXT_START_CODE) {
  792.     flush_bits32;
  793.     if (vid_stream->group.ext_data) {
  794.       free(vid_stream->group.ext_data);
  795.       vid_stream->group.ext_data = NULL;
  796.     }
  797.     vid_stream->group.ext_data = get_ext_data();
  798.     show_bits32(data);
  799.   }
  800.  
  801.   /* If next start code is user data, parse off user data. */
  802.  
  803.   if (data == USER_START_CODE) {
  804.     flush_bits32;
  805.     if (vid_stream->group.user_data) {
  806.       free(vid_stream->group.user_data);
  807.       vid_stream->group.user_data = NULL;
  808.     }
  809.     vid_stream->group.user_data = get_ext_data();
  810.   }
  811.  
  812.   return PARSE_OK;
  813. }
  814.  
  815.  
  816.  
  817. /*
  818.  *--------------------------------------------------------------
  819.  *
  820.  * ParsePicture --
  821.  *
  822.  *      Parses picture header. Marks picture to be presented
  823.  *      at particular time given a time stamp.
  824.  *
  825.  * Results:
  826.  *      Values from picture header put into video stream structure.
  827.  *
  828.  * Side effects:
  829.  *      Bit stream irreversibly parsed.
  830.  *
  831.  *--------------------------------------------------------------
  832.  */
  833.  
  834. static int ParsePicture(VidStream *vid_stream, TimeStamp time_stamp)
  835. {
  836.   unsigned int data;
  837.   int i;
  838.  
  839.   /* Flush header start code. */
  840.   flush_bits32;
  841.  
  842.   /* Parse off temporal reference. */
  843.   get_bits10(vid_stream->picture.temp_ref);
  844.  
  845.   /* Parse of picture type. */
  846.   get_bits3(vid_stream->picture.code_type);
  847.  
  848.   if ((vid_stream->picture.code_type == B_TYPE) &&
  849.       (No_B_Flag ||
  850.        (vid_stream->past == NULL) ||
  851.        (vid_stream->future == NULL)))
  852.     return SKIP_PICTURE;
  853.  
  854.   if ((vid_stream->picture.code_type == P_TYPE) &&
  855.       (No_P_Flag || (vid_stream->future == NULL)))
  856.     return SKIP_PICTURE;
  857.  
  858. #ifdef ANALYSIS
  859.   StartTime();
  860.   stat_a[0].frametype = vid_stream->picture.code_type;
  861.   stat_a[0].number = 1;
  862.   stat_a[0].totsize = 45;
  863.   pictureSizeCount = bitCountRead();
  864. #endif
  865.  
  866.   /* Parse off vbv buffer delay value. */
  867.  
  868.   get_bits16(vid_stream->picture.vbv_delay);
  869.  
  870.   /* If P or B type frame... */
  871.  
  872.   if ((vid_stream->picture.code_type == 2) || (vid_stream->picture.code_type == 3)) {
  873.  
  874.     /* Parse off forward vector full pixel flag. */
  875.     get_bits1(vid_stream->picture.full_pel_forw_vector);
  876.  
  877.     /* Parse of and decode forw_r_code into forw_r_size and forw_f. */
  878.  
  879.     get_bits3(vid_stream->picture.forw_r_size) - 1;
  880.     vid_stream->picture.forw_f = (1 << vid_stream->picture.forw_r_size);
  881.   }
  882.  
  883.   /* If B type frame... */
  884.  
  885.   if (vid_stream->picture.code_type == 3) {
  886.  
  887.     /* Parse off back vector full pixel flag. */
  888.     get_bits1(vid_stream->picture.full_pel_back_vector);
  889.  
  890.     /* Parse off and decode back_r_code into back_r_size and back_f. */
  891.  
  892.     get_bits3(vid_stream->picture.back_r_size) - 1;
  893.     vid_stream->picture.back_f = (1 << vid_stream->picture.back_r_size);
  894.   }
  895.  
  896.   /* Get extra bit picture info. */
  897.  
  898.   if (vid_stream->picture.extra_info) {
  899.     free(vid_stream->picture.extra_info);
  900.     vid_stream->picture.extra_info = NULL;
  901.   }
  902.   vid_stream->picture.extra_info = get_extra_bit_info();
  903.  
  904.   /* Goto next start code. */
  905.  
  906.   next_start_code();
  907.  
  908.   /* If start code is extension start code, parse off extension data. */
  909.  
  910.   if ((show_bits32(data)) == EXT_START_CODE) {
  911.     flush_bits32;
  912.     if (vid_stream->picture.ext_data) {
  913.       free(vid_stream->picture.ext_data);
  914.       vid_stream->picture.ext_data = NULL;
  915.     }
  916.     vid_stream->picture.ext_data = get_ext_data();
  917.     show_bits32(data);
  918.   }
  919.  
  920.   /* If start code is user start code, parse off user data. */
  921.  
  922.   if (data == USER_START_CODE) {
  923.     flush_bits32;
  924.     if (vid_stream->picture.user_data) {
  925.       free(vid_stream->picture.user_data);
  926.       vid_stream->picture.user_data = NULL;
  927.     }
  928.     vid_stream->picture.user_data = get_ext_data();
  929.   }
  930.  
  931.   /* Find a pict image structure in ring buffer not currently locked. */
  932.   i = 0;
  933.   while (vid_stream->ring[i]->locked != 0) {
  934.     if (++i >= RING_BUF_SIZE) {
  935.       perror("Fatal error. Ring buffer full.");
  936.       exit(1);
  937.     }
  938.   }
  939.  
  940.   /* Set current pict image structure to the one just found in ring. */
  941.  
  942.   vid_stream->current = vid_stream->ring[i];
  943.  
  944.   /* Set time stamp. */
  945.  
  946.   vid_stream->current->show_time = time_stamp;
  947.  
  948.   /* Reset past macroblock address field. */
  949.  
  950.   vid_stream->mblock.past_mb_addr = -1;
  951.  
  952.   return PARSE_OK;
  953. }
  954.  
  955.  
  956.  
  957. /*
  958.  *--------------------------------------------------------------
  959.  *
  960.  * ParseSlice --
  961.  *
  962.  *      Parses off slice header.
  963.  *
  964.  * Results:
  965.  *      Values found in slice header put into video stream structure.
  966.  *
  967.  * Side effects:
  968.  *      Bit stream irreversibly parsed.
  969.  *
  970.  *--------------------------------------------------------------
  971.  */
  972.  
  973. static int ParseSlice(VidStream *vid_stream)
  974. {
  975.   /* Flush slice start code. */
  976.  
  977.   flush_bits(24);
  978.  
  979.   /* Parse off slice vertical position. */
  980.  
  981.   get_bits8(vid_stream->slice.vert_pos);
  982.  
  983.   /* Parse off quantization scale. */
  984.  
  985.   get_bits5(vid_stream->slice.quant_scale);
  986.  
  987.   /* Parse off extra bit slice info. */
  988.  
  989.   if (vid_stream->slice.extra_info) {
  990.     free(vid_stream->slice.extra_info);
  991.     vid_stream->slice.extra_info = NULL;
  992.   }
  993.   vid_stream->slice.extra_info = get_extra_bit_info();
  994.  
  995.   /* Reset past intrablock address. */
  996.  
  997.   vid_stream->mblock.past_intra_addr = -2;
  998.  
  999.   /* Reset previous recon motion vectors. */
  1000.  
  1001.   vid_stream->mblock.recon_right_for_prev = 0;
  1002.   vid_stream->mblock.recon_down_for_prev = 0;
  1003.   vid_stream->mblock.recon_right_back_prev = 0;
  1004.   vid_stream->mblock.recon_down_back_prev = 0;
  1005.  
  1006.   /* Reset macroblock address. */
  1007.  
  1008.   vid_stream->mblock.mb_address = ((short)(vid_stream->slice.vert_pos - 1) * (short)vid_stream->mb_width) - 1;
  1009.  
  1010.   /* Reset past dct dc y, cr, and cb values. */
  1011.  
  1012.   vid_stream->block.dct_dc_y_past = 1024;
  1013.   vid_stream->block.dct_dc_cr_past = 1024;
  1014.   vid_stream->block.dct_dc_cb_past = 1024;
  1015.  
  1016.   return PARSE_OK;
  1017. }
  1018.  
  1019.  
  1020.  
  1021. /*
  1022.  *--------------------------------------------------------------
  1023.  *
  1024.  * ParseMacroBlock --
  1025.  *
  1026.  *      Parseoff macroblock. Reconstructs DCT values. Applies
  1027.  *      inverse DCT, reconstructs motion vectors, calculates and
  1028.  *      set pixel values for macroblock in current pict image
  1029.  *      structure.
  1030.  *
  1031.  * Results:
  1032.  *      Here's where everything really happens. Welcome to the
  1033.  *      heart of darkness.
  1034.  *
  1035.  * Side effects:
  1036.  *      Bit stream irreversibly parsed off.
  1037.  *
  1038.  *--------------------------------------------------------------
  1039.  */
  1040.  
  1041. static int ParseMacroBlock(VidStream *vid_stream)
  1042. {
  1043.     int addr_incr, mask, i;
  1044.     int recon_right_for, recon_down_for, recon_right_back, recon_down_back, zero_block_flag;
  1045.     int mb_data;
  1046.  
  1047. #ifdef ANALYSIS
  1048.     mbSizeCount = bitCountRead();
  1049. #endif
  1050.  
  1051.     /*
  1052.      * Parse off macroblock address increment and add to macroblock address.
  1053.      */
  1054.     do {
  1055.         DecodeMBAddrInc(addr_incr);
  1056.         if (addr_incr == MB_ESCAPE) {
  1057.             vid_stream->mblock.mb_address += 33;
  1058.             addr_incr = MB_STUFFING;
  1059.         }
  1060.     } while (addr_incr == MB_STUFFING);
  1061.     vid_stream->mblock.mb_address += addr_incr;
  1062.  
  1063.     if (vid_stream->mblock.mb_address > ((short)vid_stream->mb_height * (short)vid_stream->mb_width - 1))
  1064.         return SKIP_TO_START_CODE;
  1065.  
  1066.     /*
  1067.      * If macroblocks have been skipped, process skipped macroblocks.
  1068.      */
  1069.  
  1070.     if (vid_stream->mblock.mb_address - vid_stream->mblock.past_mb_addr > 1) {
  1071.         if (vid_stream->picture.code_type == P_TYPE)
  1072.             ProcessSkippedPFrameMBlocks(vid_stream);
  1073.         else if (vid_stream->picture.code_type == B_TYPE)
  1074.             ProcessSkippedBFrameMBlocks(vid_stream);
  1075.     }
  1076.  
  1077.     /* Set past macroblock address to current macroblock address. */
  1078.     vid_stream->mblock.past_mb_addr = vid_stream->mblock.mb_address;
  1079.  
  1080.     /* Based on picture type decode macroblock type. */
  1081.     switch (vid_stream->picture.code_type) {
  1082.         case I_TYPE:
  1083.             DecodeMBTypeI(mb_data, vid_stream->mblock.mb_intra);
  1084.             break;
  1085.         case P_TYPE:
  1086.             DecodeMBTypeP(mb_data, vid_stream->mblock.mb_intra);
  1087.             break;
  1088.         case B_TYPE:
  1089.             DecodeMBTypeB(mb_data, vid_stream->mblock.mb_intra);
  1090.             break;
  1091.     }
  1092.  
  1093.     /* If quantization flag set, parse off new quantization scale. */
  1094.     if (mb_data&MB_quant) {
  1095.         get_bits5(vid_stream->slice.quant_scale);
  1096.     }
  1097.  
  1098.   /* If forward motion vectors exist... */
  1099.   if (mb_data&MB_motion_forw) {
  1100.  
  1101.     /* Parse off and decode horizontal forward motion vector. */
  1102.     DecodeMotionVectors(vid_stream->mblock.motion_h_forw_code);
  1103.  
  1104.     /* If horiz. forward r data exists, parse off. */
  1105.  
  1106.     if ((vid_stream->picture.forw_f != 1) && (vid_stream->mblock.motion_h_forw_code != 0)) {
  1107.       get_bitsn(vid_stream->picture.forw_r_size, vid_stream->mblock.motion_h_forw_r);
  1108.     }
  1109.     /* Parse off and decode vertical forward motion vector. */
  1110.     DecodeMotionVectors(vid_stream->mblock.motion_v_forw_code);
  1111.  
  1112.     /* If vert. forw. r data exists, parse off. */
  1113.  
  1114.     if ((vid_stream->picture.forw_f != 1) && (vid_stream->mblock.motion_v_forw_code != 0)) {
  1115.       get_bitsn(vid_stream->picture.forw_r_size, vid_stream->mblock.motion_v_forw_r);
  1116.     }
  1117.   }
  1118.   /* If back motion vectors exist... */
  1119.   if (mb_data&MB_motion_back) {
  1120.  
  1121.     /* Parse off and decode horiz. back motion vector. */
  1122.     DecodeMotionVectors(vid_stream->mblock.motion_h_back_code);
  1123.  
  1124.     /* If horiz. back r data exists, parse off. */
  1125.  
  1126.     if ((vid_stream->picture.back_f != 1) && (vid_stream->mblock.motion_h_back_code != 0)) {
  1127.       get_bitsn(vid_stream->picture.back_r_size, vid_stream->mblock.motion_h_back_r);
  1128.     }
  1129.     /* Parse off and decode vert. back motion vector. */
  1130.     DecodeMotionVectors(vid_stream->mblock.motion_v_back_code);
  1131.  
  1132.     /* If vert. back r data exists, parse off. */
  1133.  
  1134.     if ((vid_stream->picture.back_f != 1) && (vid_stream->mblock.motion_v_back_code != 0)) {
  1135.       get_bitsn(vid_stream->picture.back_r_size, vid_stream->mblock.motion_v_back_r);
  1136.     }
  1137.   }
  1138. #ifdef ANALYSIS
  1139.     if (vid_stream->mblock.mb_intra) {
  1140.         stat_a[0].i_mbnum++;
  1141.         mbCBPPtr = stat_a[0].i_mbcbp;
  1142.         mbCoeffPtr = stat_a[0].i_mbcoeff;
  1143.         mbSizePtr = &(stat_a[0].i_mbsize);
  1144.     } else if ((mb_data&(MB_motion_back | MB_motion_forw)) == (MB_motion_back | MB_motion_forw)) {
  1145.         stat_a[0].bi_mbnum++;
  1146.         mbCBPPtr = stat_a[0].bi_mbcbp;
  1147.         mbCoeffPtr = stat_a[0].bi_mbcoeff;
  1148.         mbSizePtr = &(stat_a[0].bi_mbsize);
  1149.     } else if (mb_data&MB_motion_back) {
  1150.         stat_a[0].b_mbnum++;
  1151.         mbCBPPtr = stat_a[0].b_mbcbp;
  1152.         mbCoeffPtr = stat_a[0].b_mbcoeff;
  1153.         mbSizePtr = &(stat_a[0].b_mbsize);
  1154.     } else {
  1155.         stat_a[0].p_mbnum++;
  1156.         mbCBPPtr = stat_a[0].p_mbcbp;
  1157.         mbCoeffPtr = stat_a[0].p_mbcoeff;
  1158.         mbSizePtr = &(stat_a[0].p_mbsize);
  1159.     }
  1160. #endif
  1161.  
  1162.     /* If mblock pattern flag set, parse and decode CBP (code block pattern). */
  1163.     if (mb_data&MB_pattern) {
  1164.         DecodeCBP(vid_stream->mblock.cbp);
  1165.     } else /* Otherwise, set CBP to zero. */
  1166.         vid_stream->mblock.cbp = 0;
  1167.  
  1168. #ifdef ANALYSIS
  1169.     mbCBPPtr[vid_stream->mblock.cbp]++;
  1170. #endif
  1171.  
  1172.   /* Reconstruct motion vectors depending on picture type. */
  1173.   if (vid_stream->picture.code_type == P_TYPE) {
  1174.  
  1175.     /*
  1176.      * If no forw motion vectors, reset previous and current vectors to 0.
  1177.      */
  1178.  
  1179.     if (!(mb_data&MB_motion_forw)) {
  1180.       recon_right_for = 0;
  1181.       recon_down_for = 0;
  1182.       vid_stream->mblock.recon_right_for_prev = 0;
  1183.       vid_stream->mblock.recon_down_for_prev = 0;
  1184.     }
  1185.     /*
  1186.      * Otherwise, compute new forw motion vectors. Reset previous vectors to
  1187.      * current vectors.
  1188.      */
  1189.  
  1190.     else {
  1191.       ComputeForwVector(&recon_right_for, &recon_down_for);
  1192.     }
  1193.   }
  1194.   if (vid_stream->picture.code_type == B_TYPE) {
  1195.  
  1196.     /* Reset prev. and current vectors to zero if mblock is intracoded. */
  1197.  
  1198.     if (vid_stream->mblock.mb_intra) {
  1199.       vid_stream->mblock.recon_right_for_prev = 0;
  1200.       vid_stream->mblock.recon_down_for_prev = 0;
  1201.       vid_stream->mblock.recon_right_back_prev = 0;
  1202.       vid_stream->mblock.recon_down_back_prev = 0;
  1203.     } else {
  1204.  
  1205.       /* If no forw vectors, current vectors equal prev. vectors. */
  1206.  
  1207.       if (!(mb_data&MB_motion_forw)) {
  1208.     recon_right_for = vid_stream->mblock.recon_right_for_prev;
  1209.     recon_down_for = vid_stream->mblock.recon_down_for_prev;
  1210.       }
  1211.       /*
  1212.        * Otherwise compute forw. vectors. Reset prev vectors to new values.
  1213.        */
  1214.  
  1215.       else {
  1216.         ComputeForwVector(&recon_right_for, &recon_down_for);
  1217.       }
  1218.  
  1219.       /* If no back vectors, set back vectors to prev back vectors. */
  1220.  
  1221.       if (!(mb_data&MB_motion_back)) {
  1222.     recon_right_back = vid_stream->mblock.recon_right_back_prev;
  1223.     recon_down_back = vid_stream->mblock.recon_down_back_prev;
  1224.       }
  1225.       /* Otherwise compute new vectors and reset prev. back vectors. */
  1226.  
  1227.       else {
  1228.     ComputeBackVector(&recon_right_back, &recon_down_back);
  1229.       }
  1230.  
  1231.       /*
  1232.        * Store vector existance flags in structure for possible skipped
  1233.        * macroblocks to follow.
  1234.        */
  1235.  
  1236.       if(mb_data<0)
  1237.     vid_stream->mblock.bpict_past_forw = vid_stream->mblock.bpict_past_back = -1;
  1238.       else {
  1239.     vid_stream->mblock.bpict_past_forw = mb_data&MB_motion_forw;
  1240.     vid_stream->mblock.bpict_past_back = mb_data&MB_motion_back;
  1241.       }
  1242.  
  1243.     }
  1244.   }
  1245.  
  1246.   /* For each possible block in macroblock. */
  1247.   if (ditherType == GRAY_DITHER) {
  1248.     for (mask = 32, i = 0; i < 4; mask >>= 1, i++) {
  1249.  
  1250.       /* If block exists... */
  1251.       if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & mask)) {
  1252.     zero_block_flag = 0;
  1253.     ParseReconBlock(i);
  1254.       } else
  1255.     zero_block_flag = 1;
  1256.  
  1257.       /* If macroblock is intra coded... */
  1258.       if (vid_stream->mblock.mb_intra) {
  1259.     ReconIMBlock(vid_stream, i);
  1260.       } else if ((mb_data&(MB_motion_forw | MB_motion_back)) == (MB_motion_forw | MB_motion_back)) {
  1261.     ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1262.               recon_right_back, recon_down_back, zero_block_flag);
  1263.       } else if ((mb_data&MB_motion_forw) || (vid_stream->picture.code_type == P_TYPE)) {
  1264.     ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1265.              zero_block_flag);
  1266.       } else if (mb_data&MB_motion_back) {
  1267.     ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back,
  1268.              zero_block_flag);
  1269.       }
  1270.     }
  1271.     /* Kill the Chrominace blocks... */
  1272.     if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & 0x2)) ParseAwayBlock(4);
  1273.     if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & 0x1)) ParseAwayBlock(5);
  1274.   } else {
  1275.       for (mask = 32, i = 0; i < 6; mask >>= 1, i++) {
  1276.     
  1277.     /* If block exists... */
  1278.     if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & mask)) {
  1279.       zero_block_flag = 0;
  1280.       ParseReconBlock(i);
  1281.     } else
  1282.       zero_block_flag = 1;
  1283.     
  1284.     /* If macroblock is intra coded... */
  1285.     if (vid_stream->mblock.mb_intra) {
  1286.       ReconIMBlock(vid_stream, i);
  1287.     } else if ((mb_data&(MB_motion_forw | MB_motion_back)) == (MB_motion_forw | MB_motion_back)) {
  1288.       ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1289.             recon_right_back, recon_down_back, zero_block_flag);
  1290.     } else if ((mb_data&MB_motion_forw) || (vid_stream->picture.code_type == P_TYPE)) {
  1291.       ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1292.                zero_block_flag);
  1293.     } else if (mb_data&MB_motion_back) {
  1294.       ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back,
  1295.                zero_block_flag);
  1296.     }
  1297.       }
  1298.   }
  1299.  
  1300.   /* If D Type picture, flush marker bit. */
  1301.   if (vid_stream->picture.code_type == 4) flush_bits(1);
  1302.  
  1303.   /* If macroblock was intracoded, set macroblock past intra address. */
  1304.   if (vid_stream->mblock.mb_intra) vid_stream->mblock.past_intra_addr = vid_stream->mblock.mb_address;
  1305.  
  1306. #ifdef ANALYSIS
  1307.   *mbSizePtr += bitCountRead() - mbSizeCount;
  1308. #endif
  1309.  
  1310.   return PARSE_OK;
  1311. }
  1312.  
  1313. #ifndef MYRECON
  1314.  
  1315. /*MR
  1316.  *--------------------------------------------------------------
  1317.  *
  1318.  * ReconIMBlock --
  1319.  *
  1320.  *    Reconstructs intra coded macroblock.
  1321.  *
  1322.  * Results:
  1323.  *    None.
  1324.  *
  1325.  * Side effects:
  1326.  *    None.
  1327.  *
  1328.  *--------------------------------------------------------------
  1329.  */
  1330.  
  1331. static void ReconIMBlock(VidStream *vid_stream, int bnum)
  1332. {
  1333.   int row, col, row_size;
  1334.   unsigned char *dest;
  1335.  
  1336.   row_size = vid_stream->mb_width;
  1337.   /* Calculate macroblock row and column from address. */
  1338.   row = vid_stream->mblock.mb_address / row_size;
  1339.   col = vid_stream->mblock.mb_address % row_size;
  1340.  
  1341.   /* If block is luminance block... */
  1342.  
  1343.   if (bnum < 4) {
  1344.  
  1345.     /* Calculate row and col values for upper left pixel of block. */
  1346.     row <<= 4;
  1347.     col <<= 4;
  1348.     if (bnum > 1) row += 8;
  1349.     if (bnum & 1) col += 8;
  1350.  
  1351.     /* Set dest to luminance plane of current pict image. */
  1352.     dest = vid_stream->current->luminance;
  1353.  
  1354.     /* Establish row size. */
  1355.     row_size *= 16;
  1356.   }
  1357.   /* Otherwise if block is Cr block... */
  1358.  
  1359.   else if (bnum == 4) {
  1360.  
  1361.     /* Set dest to Cr plane of current pict image. */
  1362.     dest = vid_stream->current->Cr;
  1363.  
  1364.     /* Establish row size. */
  1365.     row_size <<= 3;
  1366.  
  1367.     /* Calculate row,col for upper left pixel of block. */
  1368.     row <<= 3;
  1369.     col <<= 3;
  1370.   }
  1371.   /* Otherwise block is Cb block, and ... */
  1372.  
  1373.   else {
  1374.  
  1375.     /* Set dest to Cb plane of current pict image. */
  1376.     dest = vid_stream->current->Cb;
  1377.  
  1378.     /* Establish row size. */
  1379.     row_size <<= 3;
  1380.  
  1381.     /* Calculate row,col for upper left pixel value of block. */
  1382.     row <<= 3;
  1383.     col <<= 3;
  1384.   }
  1385.  
  1386.   /*
  1387.    * For each pixel in block, set to cropped reconstructed value from inverse dct.
  1388.    */
  1389.   IM_reconstruct(dest + row * row_size + col, &vid_stream->block.dct_recon[0][0], row_size);
  1390. }
  1391.  
  1392.  
  1393. /* MR
  1394.  *--------------------------------------------------------------
  1395.  *
  1396.  * ReconPMBlock --
  1397.  *
  1398.  *    Reconstructs forward predicted macroblocks.
  1399.  *
  1400.  * Results:
  1401.  *      None.
  1402.  *
  1403.  * Side effects:
  1404.  *      None.
  1405.  *
  1406.  *--------------------------------------------------------------
  1407.  */
  1408. static void ReconPMBlock(VidStream *vid_stream, int bnum, int recon_right_for, int recon_down_for, int zflag)
  1409. {
  1410.   int row, col, row_size;
  1411.   unsigned char *dest, *past, *rindex2;
  1412.   int right_half_for, down_half_for;
  1413.  
  1414.   row_size = vid_stream->mb_width;
  1415.   /* Calculate macroblock row and column from address. */
  1416.   row = vid_stream->mblock.mb_address / row_size;
  1417.   col = vid_stream->mblock.mb_address % row_size;
  1418.  
  1419.   if (bnum < 4) {
  1420.     /* Calculate right_for, down_for motion vectors. */
  1421.  
  1422.     right_half_for = recon_right_for & 0x1;
  1423.     down_half_for = recon_down_for & 0x1;
  1424.     recon_right_for >>= 1;
  1425.     recon_down_for >>= 1;
  1426.  
  1427.     /* Set dest to luminance plane of current pict image. */
  1428.     dest = vid_stream->current->luminance;
  1429.  
  1430.     if (vid_stream->picture.code_type == B_TYPE) {
  1431.       if (vid_stream->past) past = vid_stream->past->luminance;
  1432.     } else {
  1433.       /* Set predicitive frame to current future frame. */
  1434.       if (vid_stream->future) past = vid_stream->future->luminance;
  1435.     }
  1436.  
  1437.     /* Establish row size. */
  1438.     row_size <<= 4;
  1439.  
  1440.     /* Calculate row,col of upper left pixel in block. */
  1441.     row <<= 4;
  1442.     col <<= 4;
  1443.     if (bnum > 1) row += 8;
  1444.     if (bnum & 1) col += 8;
  1445.  
  1446.   }
  1447.   /* Otherwise, block is NOT luminance block, ... */
  1448.   else {
  1449.     /* Construct motion vectors. */
  1450.     right_half_for = (recon_right_for & 0x2)>>1;
  1451.     down_half_for = recon_down_for & 0x2;
  1452.     recon_right_for >>= 2;
  1453.     recon_down_for >>= 2;
  1454.  
  1455.     /* Establish row size. */
  1456.     row_size <<= 3;
  1457.  
  1458.     /* Calculate row,col of upper left pixel in block. */
  1459.     row <<= 3;
  1460.     col <<= 3;
  1461.  
  1462.     /* If block is Cr block... */
  1463.  
  1464.     if (bnum == 4) {
  1465.       /* Set dest to Cr plane of current pict image. */
  1466.       dest = vid_stream->current->Cr;
  1467.  
  1468.       if (vid_stream->picture.code_type == B_TYPE) {
  1469.     if (vid_stream->past) past = vid_stream->past->Cr;
  1470.       } else {
  1471.     if (vid_stream->future) past = vid_stream->future->Cr;
  1472.       }
  1473.     }
  1474.     /* Otherwise, block is Cb block... */
  1475.     else {
  1476.       /* Set dest to Cb plane of current pict image. */
  1477.       dest = vid_stream->current->Cb;
  1478.  
  1479.       if (vid_stream->picture.code_type == B_TYPE) {
  1480.     if (vid_stream->past) past = vid_stream->past->Cb;
  1481.       } else {
  1482.     if (vid_stream->future) past = vid_stream->future->Cb;
  1483.       }
  1484.     }
  1485.   }
  1486.  
  1487.   /* For each pixel in block... */
  1488.     dest += ((short)row * (short)row_size) + col;
  1489.     past += (short)(row + recon_down_for) * (short)row_size + col + recon_right_for;
  1490.  
  1491.     /*
  1492.      * Calculate predictive pixel value based on motion vectors and copy to
  1493.      * dest plane.
  1494.      */
  1495.  
  1496.     if ((!down_half_for) && (!right_half_for)) {
  1497.       if (!zflag)
  1498.     BMcm_reconstruct(dest, past, &(vid_stream->block.dct_recon[0][0]), row_size);
  1499.       else
  1500.     BM_reconstruct(dest, past, row_size);
  1501.     } else {
  1502.       rindex2 = past + right_half_for + (down_half_for?row_size:0);
  1503.       if (!zflag)
  1504.     BIMcm_reconstruct(dest, past, rindex2, &(vid_stream->block.dct_recon[0][0]), row_size);
  1505.       else
  1506.     BIM_reconstruct(dest, past, rindex2, row_size);
  1507.     }
  1508.  
  1509. }
  1510.  
  1511.  
  1512. /* MR
  1513.  *--------------------------------------------------------------
  1514.  *
  1515.  * ReconBMBlock --
  1516.  *
  1517.  *    Reconstructs back predicted macroblocks.
  1518.  *
  1519.  * Results:
  1520.  *      None.
  1521.  *
  1522.  * Side effects:
  1523.  *      None.
  1524.  *
  1525.  *--------------------------------------------------------------
  1526.  */
  1527.  
  1528. static void ReconBMBlock(VidStream *vid_stream, int bnum, int recon_right_back, int recon_down_back, int zflag)
  1529. {
  1530.   int row, col, row_size;
  1531.   unsigned char *dest, *future, *rindex2;
  1532.   int right_half_back, down_half_back;
  1533.  
  1534.   row_size = vid_stream->mb_width;
  1535.   /* Calculate macroblock row and column from address. */
  1536.   row = vid_stream->mblock.mb_address / row_size;
  1537.   col = vid_stream->mblock.mb_address % row_size;
  1538.  
  1539.   /* If block is luminance block... */
  1540.  
  1541.   if (bnum < 4) {
  1542.     /* Calculate right_back, down_back motion vectors. */
  1543.     right_half_back = recon_right_back & 0x1;
  1544.     down_half_back = recon_down_back & 0x1;
  1545.     recon_right_back >>= 1;
  1546.     recon_down_back >>= 1;
  1547.  
  1548.     /* Set dest to luminance plane of current pict image. */
  1549.     dest = vid_stream->current->luminance;
  1550.  
  1551.     /* If future frame exists, set future to luminance plane of future frame. */
  1552.     if (vid_stream->future) future = vid_stream->future->luminance;
  1553.  
  1554.     /* Establish row size. */
  1555.     row_size <<= 4;
  1556.  
  1557.     /* Calculate row,col of upper left pixel in block. */
  1558.     row <<= 4;
  1559.     col <<= 4;
  1560.     if (bnum > 1) row += 8;
  1561.     if (bnum & 1) col += 8;
  1562.  
  1563.   }
  1564.   /* Otherwise, block is NOT luminance block, ... */
  1565.   else {
  1566.     /* Construct motion vectors. */
  1567.     right_half_back = (recon_right_back & 0x2)>>1;    /* used as integer down there */
  1568.     down_half_back = recon_down_back & 0x2;
  1569.     recon_right_back >>= 2;
  1570.     recon_down_back >>= 2;
  1571.  
  1572.     /* Establish row size. */
  1573.     row_size <<= 3;
  1574.  
  1575.     /* Calculate row,col of upper left pixel in block. */
  1576.     row <<= 3;
  1577.     col <<= 3;
  1578.  
  1579.     /* If block is Cr block... */
  1580.  
  1581.     if (bnum == 4) {
  1582.       /* Set dest to Cr plane of current pict image. */
  1583.       dest = vid_stream->current->Cr;
  1584.  
  1585.       /* If future frame exists, set future to Cr plane of future image. */
  1586.       if (vid_stream->future) future = vid_stream->future->Cr;
  1587.     }
  1588.     /* Otherwise, block is Cb block... */
  1589.     else {
  1590.       /* Set dest to Cb plane of current pict image. */
  1591.       dest = vid_stream->current->Cb;
  1592.  
  1593.       /* If future frame exists, set future to Cb plane of future frame. */
  1594.       if (vid_stream->future) future = vid_stream->future->Cb;
  1595.     }
  1596.   }
  1597.  
  1598.   /* For each pixel in block do... */
  1599.     dest += ((short)row * (short)row_size) + col;
  1600.     future += (short)(row + recon_down_back) * (short)row_size + col + recon_right_back;
  1601.  
  1602.     if ((!right_half_back) && (!down_half_back)) {
  1603.       if (!zflag)
  1604.     BMcm_reconstruct(dest, future, &(vid_stream->block.dct_recon[0][0]), row_size);
  1605.       else
  1606.     BM_reconstruct(dest, future, row_size);
  1607.     } else {
  1608.       rindex2 = future + right_half_back + (down_half_back?row_size:0);
  1609.       if (!zflag)
  1610.     BIMcm_reconstruct(dest, future, rindex2, &(vid_stream->block.dct_recon[0][0]), row_size);
  1611.       else
  1612.     BIM_reconstruct(dest, future, rindex2, row_size);
  1613.     }
  1614. }
  1615.  
  1616.  
  1617. /* MR
  1618.  *--------------------------------------------------------------
  1619.  *
  1620.  * ReconBiMBlock --
  1621.  *
  1622.  *    Reconstructs bidirectionally predicted macroblocks.
  1623.  *
  1624.  * Results:
  1625.  *      None.
  1626.  *
  1627.  * Side effects:
  1628.  *      None.
  1629.  *
  1630.  *--------------------------------------------------------------
  1631.  */
  1632.  
  1633. static void ReconBiMBlock(VidStream *vid_stream, int bnum,
  1634.               int forw_col_start, int forw_row_start,
  1635.               int back_col_start, int back_row_start,
  1636.               int zflag)
  1637. {
  1638.   int row, col, row_size;
  1639.   unsigned char *dest, *past, *future;
  1640.  
  1641.   row_size = vid_stream->mb_width;
  1642.   /* Calculate macroblock row and column from address. */
  1643.   row = vid_stream->mblock.mb_address / row_size;
  1644.   col = vid_stream->mblock.mb_address % row_size;
  1645.  
  1646.   /* If block is luminance block... */
  1647.  
  1648.   if (bnum < 4) {
  1649.     /* Set dest to luminance plane of current pict image. */
  1650.     dest = vid_stream->current->luminance;
  1651.  
  1652.     /* If past frame exists, set past to luminance plane of past frame. */
  1653.     if (vid_stream->past) past = vid_stream->past->luminance;
  1654.  
  1655.     /*If future frame exists, set future to luminance plane of future frame. */
  1656.     if (vid_stream->future) future = vid_stream->future->luminance;
  1657.  
  1658.     /* Establish row size. */
  1659.     row_size <<= 4;
  1660.  
  1661.     /* Calculate row,col of upper left pixel in block. */
  1662.     row <<= 4;
  1663.     col <<= 4;
  1664.     if (bnum > 1) row += 8;
  1665.     if (bnum & 1) col += 8;
  1666.  
  1667.     forw_col_start = (forw_col_start>>1) + col;
  1668.     forw_row_start = (forw_row_start>>1) + row;
  1669.     back_col_start = (back_col_start>>1) + col;
  1670.     back_row_start = (back_row_start>>1) + row;
  1671.  
  1672.   }
  1673.   /* Otherwise, block is NOT luminance block, ... */
  1674.  
  1675.   else {
  1676.     /* Establish row size. */
  1677.     row_size <<= 3;
  1678.  
  1679.     /* Calculate row,col of upper left pixel in block. */
  1680.     row <<= 3;
  1681.     col <<= 3;
  1682.  
  1683.     forw_col_start = (forw_col_start>>2) + col;
  1684.     forw_row_start = (forw_row_start>>2) + row;
  1685.     back_col_start = (back_col_start>>2) + col;
  1686.     back_row_start = (back_row_start>>2) + row;
  1687.  
  1688.     /* If block is Cr block... */
  1689.  
  1690.     if (bnum == 4) {
  1691.       /* Set dest to Cr plane of current pict image. */
  1692.       dest = vid_stream->current->Cr;
  1693.  
  1694.       /* If past frame exists, set past to Cr plane of past image. */
  1695.       if (vid_stream->past) past = vid_stream->past->Cr;
  1696.  
  1697.       /* If future frame exists, set future to Cr plane of future image. */
  1698.       if (vid_stream->future) future = vid_stream->future->Cr;
  1699.     }
  1700.     /* Otherwise, block is Cb block... */
  1701.  
  1702.     else {
  1703.       /* Set dest to Cb plane of current pict image. */
  1704.       dest = vid_stream->current->Cb;
  1705.  
  1706.       /* If past frame exists, set past to Cb plane of past frame. */
  1707.       if (vid_stream->past) past = vid_stream->past->Cb;
  1708.  
  1709.       /* If future frame exists, set future to Cb plane of future frame. */
  1710.       if (vid_stream->future) future = vid_stream->future->Cb;
  1711.     }
  1712.   }
  1713.  
  1714.   dest += (short)row * (short)row_size + col;
  1715.   past += (short)forw_row_start  * (short)row_size + forw_col_start;
  1716.   future += (short)back_row_start * (short)row_size + back_col_start;
  1717.  
  1718.   if (!zflag)
  1719.     BIMcm_reconstruct(dest, past, future, &(vid_stream->block.dct_recon[0][0]), row_size);
  1720.   else
  1721.     BIM_reconstruct(dest, past, future, row_size);
  1722. }
  1723. #endif
  1724.  
  1725.  
  1726. /* MR
  1727.  *--------------------------------------------------------------
  1728.  *
  1729.  * ProcessSkippedPFrameMBlocks --
  1730.  *
  1731.  *    Processes skipped macroblocks in P frames.
  1732.  *
  1733.  * Results:
  1734.  *    Calculates pixel values for luminance, Cr, and Cb planes
  1735.  *      in current pict image for skipped macroblocks.
  1736.  *
  1737.  * Side effects:
  1738.  *    Pixel values in pict image changed.
  1739.  *
  1740.  *--------------------------------------------------------------
  1741.  */
  1742.  
  1743. static void ProcessSkippedPFrameMBlocks(VidStream *vid_stream)
  1744. {
  1745.   int row_size, row, col, addr, off;
  1746.  
  1747.   /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
  1748.  
  1749.   row_size = vid_stream->mb_width << 4;
  1750.  
  1751.   /* For each skipped macroblock, do... */
  1752.  
  1753.   addr = vid_stream->mblock.past_mb_addr + 1;
  1754.   row = (addr / vid_stream->mb_width)<<4;
  1755.   col = (addr % vid_stream->mb_width)<<4;
  1756.  
  1757.   for (; addr < vid_stream->mblock.mb_address; addr++, col+=16) {
  1758.  
  1759.     /* Calculate macroblock row and col. */
  1760.     if(col>=row_size) col=0, row+=16;
  1761.  
  1762.     /* For each row in macroblock luminance plane... */
  1763.  
  1764.     off = ((short)row * (short)row_size);
  1765.     PMB1_reconstruct(vid_stream->current->luminance + off + col,
  1766.              vid_stream->future->luminance + off + col,
  1767.              row_size >> 2);
  1768.  
  1769.     /* For each row in Cr, and Cb planes... */
  1770.  
  1771.     off >>= 2;
  1772.     off += (col>>1);
  1773.     PMB2_reconstruct(vid_stream->current->Cr + off,
  1774.              vid_stream->current->Cb + off,
  1775.              vid_stream->future->Cr + off,
  1776.              vid_stream->future->Cb + off,
  1777.              row_size >> 3);
  1778.   }
  1779.  
  1780.   vid_stream->mblock.recon_right_for_prev = 0;
  1781.   vid_stream->mblock.recon_down_for_prev = 0;
  1782. }
  1783.  
  1784.  
  1785.  
  1786.  
  1787. /* MR
  1788.  *--------------------------------------------------------------
  1789.  *
  1790.  * ProcessSkippedBFrameMBlocks --
  1791.  *
  1792.  *    Processes skipped macroblocks in B frames.
  1793.  *
  1794.  * Results:
  1795.  *    Calculates pixel values for luminance, Cr, and Cb planes
  1796.  *      in current pict image for skipped macroblocks.
  1797.  *
  1798.  * Side effects:
  1799.  *    Pixel values in pict image changed.
  1800.  *
  1801.  *--------------------------------------------------------------
  1802.  */
  1803.  
  1804. static void ProcessSkippedBFrameMBlocks(VidStream *vid_stream)
  1805. {
  1806.   int row_size, half_row, row, col, ccol, crow;
  1807.   int right_half_for, down_half_for, c_right_half_for, c_down_half_for;
  1808.   int right_half_back, down_half_back, c_right_half_back, c_down_half_back;
  1809.   int addr;
  1810.   int recon_right_for, recon_down_for, recon_right_back, recon_down_back;
  1811.   int c_right_for, c_down_for, c_right_back, c_down_back;
  1812.   unsigned char forw_lum[256];
  1813.   unsigned char forw_cr[64], forw_cb[64];
  1814.   unsigned char back_lum[256], back_cr[64], back_cb[64];
  1815.   int row_incr, half_row_incr;
  1816.   int h;
  1817.   char *lum;
  1818.  
  1819.   /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
  1820.  
  1821.   row_size = vid_stream->mb_width << 4;
  1822.   half_row = row_size >> 1;
  1823.   row_incr = row_size >> 2;
  1824.   half_row_incr =  half_row >> 2;
  1825.  
  1826.   /* Establish motion vector codes based on full pixel flag. */
  1827.  
  1828.   recon_right_for = vid_stream->mblock.recon_right_for_prev;
  1829.   recon_down_for = vid_stream->mblock.recon_down_for_prev;
  1830.   if (vid_stream->picture.full_pel_forw_vector) {
  1831.     recon_right_for <<= 1;
  1832.     recon_down_for <<= 1;
  1833.   }
  1834.  
  1835.   recon_right_back = vid_stream->mblock.recon_right_back_prev;
  1836.   recon_down_back = vid_stream->mblock.recon_down_back_prev;
  1837.   if (vid_stream->picture.full_pel_back_vector) {
  1838.     recon_right_back <<= 1;
  1839.     recon_down_back <<= 1;
  1840.   }
  1841.  
  1842.  
  1843.   /* If only one motion vector, do display copy, else do full
  1844.      calculation. 
  1845.   */
  1846.   /* Calculate motion vectors. */
  1847.   
  1848.   if (vid_stream->mblock.bpict_past_forw) {
  1849.     right_half_for = recon_right_for & 0x1;
  1850.     down_half_for = recon_down_for & 0x1;
  1851.     recon_right_for >>= 1;
  1852.     recon_down_for >>= 1;
  1853.     c_right_for = recon_right_for >> 1;
  1854.     c_down_for = recon_down_for >> 1;
  1855.     c_right_half_for = recon_right_for & 0x1;
  1856.     c_down_half_for = recon_down_for & 0x1;
  1857.     
  1858.   }
  1859.   if (vid_stream->mblock.bpict_past_back) {
  1860.     right_half_back = recon_right_back & 0x1;
  1861.     down_half_back = recon_down_back & 0x1;    
  1862.     recon_right_back >>= 1;
  1863.     recon_down_back >>= 1;
  1864.     c_right_back = recon_right_back >> 1;
  1865.     c_down_back = recon_down_back >> 1;
  1866.     c_right_half_back = recon_right_back & 0x1;
  1867.     c_down_half_back = recon_down_back & 0x1;
  1868.     
  1869.   }
  1870.   /* For each skipped macroblock, do... */
  1871.   addr = vid_stream->mblock.past_mb_addr + 1;
  1872.   row = (addr / vid_stream->mb_width)<<4;
  1873.   col = (addr % vid_stream->mb_width)<<4;
  1874.  
  1875.   for (; addr < vid_stream->mblock.mb_address; addr++, col+=16) {
  1876.     
  1877.     /* Calculate macroblock row and col. */
  1878.     if(col>=row_size) col=0, row+=16;
  1879.  
  1880.     /* Calculate upper left pixel row,col for luminance plane. */
  1881.     crow = row >> 1;
  1882.     ccol = col >> 1;
  1883.     
  1884.     /* If forward predicted, calculate prediction values. */
  1885.     
  1886.     if (vid_stream->mblock.bpict_past_forw) {
  1887.       
  1888.       ReconSkippedBlock16(vid_stream->past->luminance, forw_lum,
  1889.               row, col, row_size, recon_right_for, recon_down_for,
  1890.               right_half_for, down_half_for);
  1891.       ReconSkippedBlock8(vid_stream->past->Cr, forw_cr, crow, ccol, half_row,
  1892.              c_right_for, c_down_for, c_right_half_for, c_down_half_for);
  1893.       ReconSkippedBlock8(vid_stream->past->Cb, forw_cb, crow, ccol, half_row,
  1894.              c_right_for, c_down_for, c_right_half_for, c_down_half_for);
  1895.     }
  1896.     /* If back predicted, calculate prediction values. */
  1897.     
  1898.     if (vid_stream->mblock.bpict_past_back) {
  1899.       ReconSkippedBlock16(vid_stream->future->luminance, back_lum,
  1900.               row, col, row_size, recon_right_back, recon_down_back,
  1901.               right_half_back, down_half_back);
  1902.       ReconSkippedBlock8(vid_stream->future->Cr, back_cr, crow, ccol, half_row,
  1903.              c_right_back, c_down_back,
  1904.              c_right_half_back, c_down_half_back);
  1905.       ReconSkippedBlock8(vid_stream->future->Cb, back_cb, crow, ccol, half_row,
  1906.              c_right_back, c_down_back,
  1907.              c_right_half_back, c_down_half_back);
  1908.     }
  1909.  
  1910.     h = ((short)crow * (short)half_row) + ccol;
  1911.     lum = (vid_stream->current->luminance + ((short)row * (short)row_size) + col);
  1912.  
  1913.     if (vid_stream->mblock.bpict_past_forw && !vid_stream->mblock.bpict_past_back) {
  1914.  
  1915.       PSB1_reconstruct(lum, forw_lum, row_incr);
  1916.  
  1917.       PSB2_reconstruct(vid_stream->current->Cr + h, vid_stream->current->Cb + h,
  1918.                forw_cr, forw_cb, half_row_incr);
  1919.  
  1920.     } else if (vid_stream->mblock.bpict_past_back && !vid_stream->mblock.bpict_past_forw) {
  1921.  
  1922.       PSB1_reconstruct(lum, back_lum, row_incr);
  1923.  
  1924.       PSB2_reconstruct(vid_stream->current->Cr + h, vid_stream->current->Cb + h,
  1925.                back_cr, back_cb, half_row_incr);
  1926.     } else {
  1927.       PSB3_reconstruct(lum, forw_lum, back_lum, row_size);
  1928.  
  1929.       PSB4_reconstruct(vid_stream->current->Cr + h, vid_stream->current->Cb + h,
  1930.                forw_cr, back_cr, forw_cb, back_cb, half_row);
  1931.     }    
  1932.   }
  1933. }
  1934.  
  1935.  
  1936.  
  1937. /* MR
  1938.  *--------------------------------------------------------------
  1939.  *
  1940.  * ReconSkippedBlock -- width 16
  1941.  *
  1942.  *    Reconstructs predictive block for skipped macroblocks
  1943.  *      in B Frames.
  1944.  *
  1945.  * Results:
  1946.  *    No return values.
  1947.  *
  1948.  * Side effects:
  1949.  *    None.
  1950.  *
  1951.  *--------------------------------------------------------------
  1952.  */
  1953.  
  1954. static
  1955. void ReconSkippedBlock16(unsigned char *source, unsigned char *dest, int row, int col, int row_size,
  1956.              int right, int down, int right_half, int down_half)
  1957. {
  1958.   source += ((short)(row + down) * (short)row_size) + col + right;
  1959.  
  1960.   if ((!right_half) && (!down_half))
  1961.     RSB1_reconstruct(dest, source, row_size);
  1962.   else 
  1963.     RSB2_reconstruct(dest, source, source + right_half + ((short)row_size * (short)down_half), row_size);
  1964. }
  1965.  
  1966. /* MR
  1967.  *--------------------------------------------------------------
  1968.  *
  1969.  * ReconSkippedBlock -- width 8
  1970.  *
  1971.  *    Reconstructs predictive block for skipped macroblocks
  1972.  *      in B Frames.
  1973.  *
  1974.  * Results:
  1975.  *    No return values.
  1976.  *
  1977.  * Side effects:
  1978.  *    None.
  1979.  *
  1980.  *--------------------------------------------------------------
  1981.  */
  1982.  
  1983. static
  1984. void ReconSkippedBlock8(unsigned char *source, unsigned char *dest, int row, int col, int row_size,
  1985.             int right, int down, int right_half, int down_half)
  1986. {
  1987.   source += ((short)(row + down) * (short)row_size) + col + right;
  1988.  
  1989.   if ((!right_half) && (!down_half))
  1990.     RSB3_reconstruct(dest, source, row_size);
  1991.   else 
  1992.     RSB4_reconstruct(dest, source, source + right_half + ((short)row_size * (short)down_half), row_size);
  1993. }
  1994.  
  1995.  
  1996. /*
  1997.  *--------------------------------------------------------------
  1998.  *
  1999.  * DoPictureDisplay --
  2000.  *
  2001.  *    Converts image from Lum, Cr, Cb to colormap space. Puts
  2002.  *      image in lum plane. Updates past and future frame
  2003.  *      pointers. Dithers image. Sends to display mechanism.
  2004.  *
  2005.  * Results:
  2006.  *    Pict image structure locked if displaying or if frame
  2007.  *      is needed as past or future reference.
  2008.  *
  2009.  * Side effects:
  2010.  *    Lum plane pummelled.
  2011.  *
  2012.  *--------------------------------------------------------------
  2013.  */
  2014.  
  2015. static void DoPictureDisplay(VidStream *vid_stream)
  2016. {
  2017.  
  2018.   /* init display, if needed */
  2019.  
  2020.   if(!vid_stream->display_is_initialized)
  2021.   {
  2022.     ResizeDisplay(vid_stream->h_size, vid_stream->v_size);
  2023.     vid_stream->display_is_initialized = TRUE;
  2024.   }
  2025.  
  2026.   /* Convert to colormap space and dither. */
  2027.  
  2028.   DoDitherImage(vid_stream->current->luminance, vid_stream->current->Cr,
  2029.         vid_stream->current->Cb, vid_stream->current->display,
  2030.         vid_stream->mb_height <<4, vid_stream->mb_width <<4);
  2031.  
  2032.   /* Update past and future references if needed. */
  2033.  
  2034.   if ((vid_stream->picture.code_type == I_TYPE) || (vid_stream->picture.code_type == P_TYPE)) {
  2035.     if (vid_stream->future == NULL) {
  2036.       vid_stream->future = vid_stream->current;
  2037.       vid_stream->future->locked |= FUTURE_LOCK;
  2038.     } else {
  2039.       if (vid_stream->past != NULL) {
  2040.     vid_stream->past->locked &= ~PAST_LOCK;
  2041.       }
  2042.       vid_stream->past = vid_stream->future;
  2043.       vid_stream->past->locked &= ~FUTURE_LOCK;
  2044.       vid_stream->past->locked |= PAST_LOCK;
  2045.       vid_stream->future = vid_stream->current;
  2046.       vid_stream->future->locked |= FUTURE_LOCK;
  2047.       vid_stream->current = vid_stream->past;
  2048.       ExecuteDisplay(vid_stream);
  2049.     }
  2050.   } else
  2051.     ExecuteDisplay(vid_stream);
  2052.  
  2053. }
  2054.  
  2055.  
  2056.  
  2057. /*
  2058.  *--------------------------------------------------------------
  2059.  *
  2060.  * ToggleBFlag --
  2061.  *
  2062.  *    Called to set no b frame processing flag.
  2063.  *
  2064.  * Results:
  2065.  *      No_B_Flag flag is toggled from present value to opposite value.
  2066.  *
  2067.  * Side effects:
  2068.  *      None.
  2069.  *
  2070.  *--------------------------------------------------------------
  2071.  */
  2072.  
  2073. void ToggleBFlag(void)
  2074. {
  2075.   No_B_Flag ^= 0xffff;
  2076. }
  2077.  
  2078.  
  2079. /*
  2080.  *--------------------------------------------------------------
  2081.  *
  2082.  * TogglePFlag --
  2083.  *
  2084.  *    Called to set no p frame processing flag.
  2085.  *
  2086.  * Results:
  2087.  *      No_P_Flag flag is toggled from present value to opposite value.
  2088.  *
  2089.  * Side effects:
  2090.  *      None.
  2091.  *
  2092.  *--------------------------------------------------------------
  2093.  */
  2094.  
  2095. void TogglePFlag(void)
  2096. {
  2097.   No_P_Flag ^= 0xffff;
  2098. }
  2099.